package com.tiancheng.trade.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tiancheng.trade.order.bo.CreditOrderQueryDetailBo;
import com.tiancheng.trade.order.bo.cmq.CreditOrderFundAuthFreezeBo;
import com.tiancheng.trade.order.enums.*;
import com.tiancheng.trade.order.feign.CreditSystemService;
import com.tiancheng.trade.order.mapper.CreditOrderOperationMapper;
import com.tiancheng.trade.order.model.CreditOrder;
import com.tiancheng.trade.order.model.CreditOrderOperation;
import com.tiancheng.trade.order.service.CreditOrderOperationService;
import com.tiancheng.trade.order.util.CommonUtil;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类 描 述：信用订单操作
 * 创建时间：2024-09-16 13:49
 * 创 建 人：likailun
 */
@Slf4j
@Service
public class CreditOrderOperationServiceImpl implements CreditOrderOperationService {

    @Resource
    private CreditOrderOperationMapper creditOrderOperationMapper;
    @Resource
    private CreditSystemService creditSystemService;



    @Override
    public CreditOrderOperation create(String orderId,String creditType, String operationType, String gwOrderId, String remark) {
        List<CreditOrderOperation> creditOrderOperations = creditOrderOperationMapper.selectList(
                new LambdaQueryWrapper<CreditOrderOperation>().eq(CreditOrderOperation::getOrderId, orderId)
                        .eq(CreditOrderOperation::getOperationType, operationType));
        CreditOrderOperation creditOrderOperation=null;
        if(CollectionUtils.isEmpty(creditOrderOperations)){
            creditOrderOperation=new CreditOrderOperation();
            creditOrderOperation.setOutRequestNo(generateOperateRequestNo(orderId));
        }else{
            creditOrderOperation=creditOrderOperations.get(0);
        }
        creditOrderOperation.setOrderId(orderId);
        creditOrderOperation.setOperationType(operationType);
        creditOrderOperation.setAmount(0);
        creditOrderOperation.setTotalFreezeAmount(0);
        creditOrderOperation.setTotalPayAmount(0);
        creditOrderOperation.setRestAmount(0);
        creditOrderOperation.setTotalFreezeCreditAmount(0);
        creditOrderOperation.setTotalFreezeFundAmount(0);
        creditOrderOperation.setTotalPayCreditAmount(0);
        creditOrderOperation.setTotalPayFundAmount(0);
        creditOrderOperation.setRestCreditAmount(0);
        creditOrderOperation.setRestFundAmount(0);
        creditOrderOperation.setCreditAmount(0);
        creditOrderOperation.setFundAmount(0);
        creditOrderOperation.setGwOrderId(gwOrderId);
        creditOrderOperation.setRemark(remark);
        creditOrderOperation.setCreditType(creditType);
        creditOrderOperation.setAlipayAuthNo(StringUtils.isEmpty(creditOrderOperation.getAlipayAuthNo())?"":creditOrderOperation.getAlipayAuthNo());
        if(creditOrderOperation.getCreatedDt()==null){
            creditOrderOperation.setCreatedDt(LocalDateTime.now());
        }
        if(creditOrderOperation.getId()!=null){
            creditOrderOperation.setLastUpdDt(LocalDateTime.now());
            creditOrderOperationMapper.update(creditOrderOperation,new LambdaQueryWrapper<CreditOrderOperation>()
                    .eq(CreditOrderOperation::getId,creditOrderOperation.getId()));
        }else{
            creditOrderOperationMapper.insert(creditOrderOperation);
        }
        return creditOrderOperation;
    }

    @Override
    public void updatePaidOperation(String orderId, String alipayAuthNo, Integer amount) {
        List<CreditOrderOperation> creditOrderOperations = creditOrderOperationMapper.selectList(
                new LambdaQueryWrapper<CreditOrderOperation>().eq(CreditOrderOperation::getOrderId, orderId)
                .eq(CreditOrderOperation::getOperationType, CreditOrderOperationTypeEnum.PAY.getCode()));
        if(!CollectionUtils.isEmpty(creditOrderOperations)){
            for (CreditOrderOperation creditOrderOperation : creditOrderOperations) {
                creditOrderOperation.setAlipayAuthNo(alipayAuthNo);
                creditOrderOperation.setAmount(amount);
                creditOrderOperation.setOperationStatus(CreditOrderOperationStatusEnum.SUCCESS.getCode());
                creditOrderOperation.setLastUpdDt(LocalDateTime.now());
                creditOrderOperationMapper.update(creditOrderOperation,new LambdaQueryWrapper<CreditOrderOperation>()
                        .eq(CreditOrderOperation::getId,creditOrderOperation.getId()));
            }
        }
    }

    @Override
    public void save(CreditOrderOperation creditOrderOperation) {
        if(creditOrderOperation==null){
            return;
        }
        if(creditOrderOperation.getCreatedDt()==null){
            creditOrderOperation.setCreatedDt(LocalDateTime.now());
        }
        if(creditOrderOperation.getId()!=null){
            creditOrderOperation.setLastUpdDt(LocalDateTime.now());
            this.creditOrderOperationMapper.update(creditOrderOperation,new LambdaQueryWrapper<CreditOrderOperation>()
                    .eq(CreditOrderOperation::getId,creditOrderOperation.getId()));
        }else{
            this.creditOrderOperationMapper.insert(creditOrderOperation);
        }

    }

    @Override
    public CreditOrderOperation queryByOrderIdAndOperationType(String orderId, String operationType) {
        List<CreditOrderOperation> creditOrderOperations = creditOrderOperationMapper.selectList(
                new LambdaQueryWrapper<CreditOrderOperation>().eq(CreditOrderOperation::getOrderId, orderId)
                        .eq(CreditOrderOperation::getOperationType, operationType));
        return CollectionUtils.isEmpty(creditOrderOperations)?null:creditOrderOperations.get(0);
    }

    @Override
    public CreditOrderOperation getOperationModelByRequestNoType(String requestNo, String operationType) {
        List<CreditOrderOperation> creditOrderOperations = creditOrderOperationMapper.selectList(
                new LambdaQueryWrapper<CreditOrderOperation>().eq(CreditOrderOperation::getOutRequestNo, requestNo)
                        .eq(CreditOrderOperation::getOperationType, operationType));
        return CollectionUtils.isEmpty(creditOrderOperations)?null:creditOrderOperations.get(0);
    }

    @Override
    public void updateOperation(CreditOrder creditOrder, CreditOrderFundAuthFreezeBo payNotifyBO, CreditOrderOperationTypeEnum type, String remark) {
        CreditOrderQueryDetailBo cd = creditSystemService.detailQuery(payNotifyBO.getRequestNo(),payNotifyBO.getGwOrderId(),creditOrder.getMerchantId());
        if(cd==null){
            return;
        }
        CreditOrderOperation operation = this.getOperationModelByRequestNoType(payNotifyBO.getRequestNo(), type.getCode());
        if(operation==null){
            operation=new CreditOrderOperation();
            operation.setOutRequestNo(generateOperateRequestNo(creditOrder.getOrderId()));
            operation.setCreatedDt(LocalDateTime.now());
        }
        if(!StringUtils.isEmpty(creditOrder.getAlipayAuthNo())){
            creditOrder.setAlipayAuthNo(cd.getAlipayAuthNo());
        }
        creditOrder.setTotalFreezeAmount(CommonUtil.long2Integer(cd.getTotalFreezeAmount()));
        creditOrder.setTotalFreezeCreditAmount(CommonUtil.long2Integer(cd.getTotalFreezeCreditAmount()));
        creditOrder.setTotalFreezeFundAmount(CommonUtil.long2Integer(cd.getTotalFreezeFundAmount()));
        creditOrder.setTotalPayAmount(CommonUtil.long2Integer(cd.getTotalPayAmount()));
        creditOrder.setRestAmount(CommonUtil.long2Integer(cd.getRestAmount()));
        //更新operationModel字段
        operation.setOrderId(creditOrder.getOrderId());
        operation.setAlipayAuthNo(creditOrder.getAlipayAuthNo());
        operation.setOperationId(cd.getAlipayOperationId());
        operation.setAmount(CommonUtil.long2Integer(cd.getAmount()));
        operation.setRemark(remark);
        operation.setTotalFreezeAmount(CommonUtil.long2Integer(cd.getTotalFreezeAmount()));
        operation.setTotalPayAmount(CommonUtil.long2Integer(cd.getTotalPayAmount()));
        operation.setRestAmount(CommonUtil.long2Integer(cd.getRestAmount()));
        operation.setOrderTitle(cd.getOrderTitle());
        operation.setAlipayPayerLogonId(cd.getPayerLogonId());
        operation.setAlipayPayerUserId(cd.getPayerUserId());
        operation.setExtraParam(cd.getExtraParam());
        operation.setOperationStatus(cd.getStatus());
        operation.setGmtCreate(DateTimeUtil.format(cd.getGmtCreate(),"yyyy-MM-dd HH:mm:ss"));
        operation.setPreAuthType(cd.getPreAuthType());
        operation.setTotalFreezeCreditAmount(CommonUtil.long2Integer(cd.getTotalFreezeCreditAmount()));
        operation.setTotalFreezeFundAmount(CommonUtil.long2Integer(cd.getTotalFreezeFundAmount()));
        operation.setTotalPayCreditAmount(CommonUtil.long2Integer(cd.getTotalPayCreditAmount()));
        operation.setTotalPayFundAmount(CommonUtil.long2Integer(cd.getTotalPayFundAmount()));
        operation.setRestCreditAmount(CommonUtil.long2Integer(cd.getRestCreditAmount()));
        operation.setRestFundAmount(CommonUtil.long2Integer(cd.getRestFundAmount()));
        operation.setCreditAmount(CommonUtil.long2Integer(cd.getCreditAmount()));
        operation.setFundAmount(CommonUtil.long2Integer(cd.getFundAmount()));
        operation.setGwOrderId(creditOrder.getGwOrderId());
        operation.setLastUpdDt(LocalDateTime.now());
        this.save(operation);
    }


    /**
     * 生成芝麻信用流水requestNo
     * 格式为 90 + 订单号 + 3位数字(100-999不重复)
     *
     * @return string
     */
    private String generateOperateRequestNo(String orderId) {
        String requestNo = "90" + orderId;
        List<CreditOrderOperation> outOrderIds = creditOrderOperationMapper.selectList(
                new LambdaQueryWrapper<CreditOrderOperation>().eq(CreditOrderOperation::getOrderId, orderId));
        List<Integer> existIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(outOrderIds)) {
            existIds = outOrderIds.stream().filter(c -> !StringUtils.isEmpty(c.getOutRequestNo()) && c.getOutRequestNo().startsWith(requestNo))
                    .map(c -> Integer.parseInt(c.getOutRequestNo().replace(requestNo, ""))).sorted(Comparator.comparing(Integer::intValue).reversed())
                    .collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(existIds)) {
            return requestNo + "100";
        }
        return requestNo + (existIds.get(0) + 1);
    }
}
